﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.SqlClient;

namespace Atm
{
    class CardAccounts
    {

        public static void RetrieveMoney(string CardNumber, string cardPin, decimal RequestedAmmount)
        {
            string serverString = @"Server=.\SQLEXPRESS;Database=Atm;Integrated Security=true";
            using (SqlConnection connection = new SqlConnection(serverString))
            {
                connection.Open();
                SqlTransaction trans= connection.BeginTransaction(System.Data.IsolationLevel.RepeatableRead);
                try
                {
                    ValidateRequest(CardNumber, cardPin, RequestedAmmount, connection, trans);
                    PayCash(CardNumber, cardPin, RequestedAmmount, connection, trans);
                    
                    trans.Commit();
                    Console.WriteLine("Transaction completed");
                }
                catch 
                {
                    trans.Rollback();
                    Console.WriteLine("Transaction canceled.");
                }
            }
        
        }

        private static void ValidateRequest(string CardNumber, string cardPin, decimal RequestedAmmount, SqlConnection connection, SqlTransaction trans)
        {
            SqlCommand retrieveRecord = new SqlCommand(@"SELECT * FROM CardAccounts WHERE CardNumber = @CardNumber", connection, trans);
            retrieveRecord.Parameters.Add("@CardNumber", CardNumber);
            using (SqlDataReader reader = retrieveRecord.ExecuteReader())
            {
                while (reader.Read() == true)
                {
                    string recordCardNumber = (string)reader["CardNumber"];
                    string recordCardPin = (string)reader["CardPin"];
                    decimal recordCardCash = (decimal)reader["CardCash"];
                    if (recordCardNumber != recordCardNumber)
                    {
                        throw new ArgumentOutOfRangeException("No such card number in the database.");
                    }
                    if (recordCardPin != cardPin)
                    {
                        throw new ArgumentOutOfRangeException("Wrong PIN code.");
                    }
                    if (recordCardCash < RequestedAmmount)
                    {
                        throw new ArgumentOutOfRangeException("Not enough money.");
                    }
                }
            }
        }
        private static void PayCash(string CardNumber, string cardPin, decimal RequestedAmmount, SqlConnection connection, SqlTransaction trans)
        {
            SqlCommand updateRecord = new SqlCommand(
                "UPDATE CardAccounts "+
                "SET CardCash = CardCash - @requestedAmmount "+
                "WHERE CardNumber = @cardNumber", connection, trans);
            updateRecord.Parameters.Add("@CardNumber", CardNumber);
            updateRecord.Parameters.Add("@requestedAmmount",RequestedAmmount);
            int result = updateRecord.ExecuteNonQuery();
            if (result != 1)
            {
                throw new KeyNotFoundException("Could not find card account");
            }
        }

        static void Main(string[] args)
        {
            RetrieveMoney("1234567890", "1234", 1010);

        }
    }
}
